#include <xp/net/sttp.h>
#include <xp/net/socket.h>
#include <xp/bas/memory.h>
#include <xp/bas/locale.h>
#include <xp/bas/stdlib.h>
#include <xp/bas/stdio.h>
#include <xp/bas/signal.h>
#include <xp/bas/errno.h>
#include <xp/bas/endian.h>
#include <xp/bas/string.h>
#include <xp/bas/ctype.h>

#ifdef __linux
	#include <mcheck.h>
#endif

int do_sttp (xp_sckhnd_t handle);

int quit = 0;

void set_quit (int sig)
{
	xp_signal (SIGINT, SIG_IGN);
	quit = 1;
	xp_signal (SIGINT, set_quit);
}

int xp_main (int argc, xp_char_t* argv[])
{
	xp_sckhnd_t handle;
	xp_uint16_t port;
	xp_sckadrin4_t sin;

#ifdef __linux
	mtrace ();
#endif

	xp_setlocale ();
	xp_signal (SIGINT, set_quit);

	if (argc != 2) {
		xp_printf (XP_TEXT("usage: %s port\n"), argv[0]);
		return -1;
	}

	if (xp_sckstartup() == -1) {
		xp_printf (XP_TEXT("can't startup socket subsystem\n"));
		return -1;
	}

	if ((handle = xp_sckopen(PF_INET, SOCK_STREAM, 0)) == -1) {
		xp_printf (XP_TEXT("can't create socket\n"));
		xp_sckcleanup ();
		return -1;
	}

	XP_STRTOI (port, argv[1], XP_NULL, 10);

	xp_memset (&sin, 0, xp_sizeof(sin));
	sin.sin_family = AF_INET;
	//sin.sin_addr.s_addr = inet_addr ("127.0.0.1");
	sin.sin_port = xp_hton16 (port);

	{
		int n = 1;
		xp_scksetopt (handle, SOL_SOCKET, 
			SO_REUSEADDR, &n, (xp_scklen_t)xp_sizeof(n));
	}

	if (xp_sckbind (handle, 
		(xp_sckadr_t*)&sin, (xp_scklen_t)xp_sizeof(sin)) == -1) {
		xp_printf (XP_TEXT("can't bind socket\n"));
		xp_sckclose (handle);
		xp_sckcleanup ();
		return -1;
	}

	if (xp_scklstn (handle, 5) == -1) {
		xp_printf (XP_TEXT("can't listen on socket\n"));
		xp_sckclose (handle);
		xp_sckcleanup ();
		return -1;
	}

	while (!quit) {
		xp_sckhnd_t handle2;
		xp_sckadrin4_t sin2;
		xp_scklen_t len2 = xp_sizeof(sin2);
	
		handle2 = xp_sckacpt (handle, (xp_sckadr_t*)&sin2, &len2, 1);
		if (handle2 == -1) {
			if (xp_errno == XP_ETIMEDOUT) continue;
			xp_printf (XP_TEXT("accept error\n"));
			break;
		}

		do_sttp (handle2);
		xp_sckclose (handle2);
	}

	xp_sckclose (handle);
	xp_sckcleanup ();

#ifdef __linux
	muntrace ();
#endif
	return 0;
}

int do_sttp (xp_sckhnd_t handle)
{
	xp_sttp_t sttp;
	xp_str_t cmd;
	xp_size_t count;

	xp_char_t ans[100];
	//xp_mcstowcs ("[\xEC\xA2\x8B\xEC\x95\x84 \xE0\xAE\xB5\xE0\xAF\x86\xE0\xAE\xB1\xE0\xAF\x8D\xE0\xAE\xB1\xE0\xAE\xBF\xE0\xAE\x95\xE0\xAF\x8D\xE0\xAE\x95\xE0\xAF\x81\xE0\xAE\xAA\xE0\xAF\x8D]", ans, xp_countof(ans));
	xp_mcstowcs ("[\xEC\xA2\x8B\xEC\x95\x84]", ans, xp_countof(ans));

	if (xp_sttp_open (&sttp, handle) == XP_NULL) {
		xp_printf (XP_TEXT("can't open sttp\n"));
		return -1;
	}

	if (xp_str_open (&cmd, 512) == XP_NULL) {
		xp_printf (XP_TEXT("can't initialize cmd\n"));
		xp_sttp_close (&sttp);
		return -1;
	}

	for (;;) {
		xp_char_t* p;
		xp_size_t* lp;

		if (xp_sttp_recv (&sttp, &cmd, &count) == -1) {
			xp_printf (XP_TEXT("sttp error - %d\n"), sttp.errnum);
			break;
		}

		lp = XP_STR_BUF(&cmd);
		while (count > 0) {
			p = (xp_char_t*)(lp + 1);
#ifdef _WIN32
			MessageBox (XP_NULL, p, XP_TEXT("sttp"), MB_OK);
#else
			xp_printf (XP_TEXT("%s\n"), p);	
#endif
			lp = (xp_size_t*)(p + *lp + 1);
			//p += xp_strlen(p) + 1;
			count--;
		}

		if (xp_sttp_send (&sttp, XP_TEXT("OK"), 1, ans) == -1) {
			xp_printf (XP_TEXT("sttp error - %d\n"), sttp.errnum);
			break;
		}
	}

	xp_str_close (&cmd);
	xp_sttp_close (&sttp);

	return 0;
}

